# -*- coding: utf-8 -*-
"""
Redis连接管理器
提供Redis连接池和基础操作方法
"""

import redis.asyncio as redis
from typing import Optional, Any
from functools import wraps
from src.config.settings import get_settings
from src.utils.logger import app_logger as logger


def ensure_redis_connected(func):
    """确保Redis已连接的装饰器"""

    @wraps(func)
    async def wrapper(self, *args, **kwargs):
        if not self.redis:
            raise RuntimeError("Redis未初始化")
        # 类型检查器提示：此时self.redis已确保不为None
        assert self.redis is not None
        return await func(self, *args, **kwargs)

    return wrapper


class RedisManager:
    """Redis连接管理器"""

    def __init__(self):
        self.redis_pool: Optional[redis.ConnectionPool] = None
        self.redis: Optional[redis.Redis] = None

    async def init_redis(self) -> None:
        """初始化Redis连接池"""
        try:
            config = get_settings()
            # 构建Redis连接URL
            password_part = (
                f":{config.REDIS_PASSWORD}@" if config.REDIS_PASSWORD else ""
            )
            redis_url = f"redis://{password_part}{config.REDIS_HOST}:{config.REDIS_PORT}/{config.REDIS_DB}"

            # 创建连接池
            self.redis_pool = redis.ConnectionPool.from_url(
                redis_url,
                max_connections=config.REDIS_MAX_CONNECTIONS,
                encoding="utf-8",
                decode_responses=True,
            )

            # 创建Redis客户端
            self.redis = redis.Redis(connection_pool=self.redis_pool)

            # 测试连接
            await self.redis.ping()
            logger.info(f"Redis连接成功: {config.REDIS_HOST}:{config.REDIS_PORT}")

        except Exception as e:
            logger.error(f"Redis连接失败: {e}")
            raise

    async def close_redis(self) -> None:
        """关闭Redis连接"""
        if self.redis:
            await self.redis.close()
        if self.redis_pool:
            await self.redis_pool.disconnect()
        logger.info("Redis连接已关闭")

    @ensure_redis_connected
    async def get(self, key: str) -> Optional[str]:
        """获取键值"""
        return await self.redis.get(key)

    @ensure_redis_connected
    async def set(self, key: str, value: Any, ex: Optional[int] = None) -> bool:
        """设置键值"""
        return await self.redis.set(key, value, ex=ex)

    @ensure_redis_connected
    async def delete(self, *keys: str) -> int:
        """删除键"""
        return await self.redis.delete(*keys)

    @ensure_redis_connected
    async def exists(self, key: str) -> bool:
        """检查键是否存在"""
        return bool(await self.redis.exists(key))

    @ensure_redis_connected
    async def expire(self, key: str, time: int) -> bool:
        """设置键过期时间"""
        return await self.redis.expire(key, time)

    @ensure_redis_connected
    async def hget(self, name: str, key: str) -> Optional[str]:
        """获取哈希表字段值"""
        return await self.redis.hget(name, key)

    @ensure_redis_connected
    async def hset(self, name: str, key: str, value: Any) -> int:
        """设置哈希表字段值"""
        return await self.redis.hset(name, key, value)

    @ensure_redis_connected
    async def hgetall(self, name: str) -> dict:
        """获取哈希表所有字段"""
        return await self.redis.hgetall(name)

    @ensure_redis_connected
    async def incr(self, key: str, amount: int = 1) -> int:
        """递增计数器"""
        return await self.redis.incr(key, amount)

    @ensure_redis_connected
    async def decr(self, key: str, amount: int = 1) -> int:
        """递减计数器"""
        return await self.redis.decr(key, amount)

    @ensure_redis_connected
    async def keys(self, pattern: str) -> list:
        """获取匹配模式的所有键"""
        return await self.redis.keys(pattern)

    @ensure_redis_connected
    async def ping(self) -> bool:
        """测试Redis连接"""
        return await self.redis.ping()

    @ensure_redis_connected
    async def sadd(self, key: str, *values: Any) -> int:
        """向集合添加元素"""
        return await self.redis.sadd(key, *values)

    @ensure_redis_connected
    async def srem(self, key: str, *values: Any) -> int:
        """从集合移除元素"""
        return await self.redis.srem(key, *values)

    @ensure_redis_connected
    async def smembers(self, key: str) -> set:
        """获取集合所有成员"""
        return await self.redis.smembers(key)

    @ensure_redis_connected
    async def sismember(self, key: str, value: Any) -> bool:
        """检查元素是否在集合中"""
        return await self.redis.sismember(key, value)


# 全局Redis管理器实例
redis_manager = RedisManager()
